package de.jmda.gen.java;

import static de.jmda.core.mproc.ProcessingUtilities.asDeclaredType;
import static de.jmda.core.mproc.ProcessingUtilities.isPrimitiveKind;
import static de.jmda.core.util.StringUtil.sb;
import static de.jmda.gen.java.naming.ImportManagerProvider.getImportManager;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import javax.lang.model.element.TypeElement;
import javax.lang.model.type.DeclaredType;
import javax.lang.model.type.TypeMirror;

import org.apache.commons.lang.StringUtils;

import de.jmda.gen.java.naming.ImportManagerProvider;

public abstract class JavaGeneratorUtils
{
	public static String asDeclaration(TypeMirror typeMirror)
	{
		if (isPrimitiveKind(typeMirror))
		{
			return typeMirror.toString();
		}

		DeclaredType declaredType = asDeclaredType(typeMirror);
		
		if (declaredType == null)
		{
			// typeMirror for void?
			return typeMirror.toString();
		}

		List<? extends TypeMirror> typeArguments = declaredType.getTypeArguments();
		
		if (typeArguments.size() == 0)
		{
			return getImportManager().useType(typeMirror.toString());
		}

		StringBuffer result = sb(outerTypeAsString(typeMirror) + "<");

		Collection<String> typeArgumentsAsDeclarations = new ArrayList<>();
		
		for (TypeMirror argumentTypeMirror : typeArguments)
		{
			typeArgumentsAsDeclarations.add(asDeclaration(argumentTypeMirror));
		}
		
		result.append(StringUtils.join(typeArgumentsAsDeclarations, ","));

		return result.append(">").toString();
	}
	
	public static String asDeclaration(TypeElement type)
	{
		return asDeclaration(type.asType());
	}

	public static String outerTypeAsString(TypeMirror typeMirror)
	{
		if (isPrimitiveKind(typeMirror))
		{
			return typeMirror.toString();
		}

		String typeMirrorString = typeMirror.toString();

		int index = typeMirrorString.indexOf('<');

		if (index > -1)
		{
			return
					ImportManagerProvider.getImportManager()
					                     .useType(typeMirrorString.substring(0, index));
		}

		return ImportManagerProvider.getImportManager().useType(typeMirrorString);
	}
}